/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package control;

import com.itextpdf.text.DocumentException;
import entidad.Bono;
import entidad.Cargo;
import entidad.Empleado;
import entidad.Falla;
import entidad.HoraExtra;
import entidad.Prestacion;
import frontera.PDF.GenerarPDF;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

/**
 *
 * @author tuareg
 */
public class GenerarReporteDeNomina {

    public void algoritmoReporteDeNomina(Calendar fechaGeneracionNomina, int tipoQuincena, ArrayList<Empleado> empleados,
                                         ArrayList<Prestacion> prestaciones, ArrayList<Cargo> cargos) throws DocumentException, IOException
    {
        ArrayList<Empleado> listaEmpleados = new ArrayList<Empleado>();
        ArrayList<Integer> diasTrabajados = new ArrayList<Integer>();
        ArrayList<Double> valorDiasTrabajados = new ArrayList<Double>();
        ArrayList<Integer[]> tiposDeHorasExtras = new ArrayList<Integer[]>();
        ArrayList<Double> valorHorasExtras = new ArrayList<Double>();
        ArrayList<Double> valorBonos = new ArrayList<Double>();
        ArrayList<Double> valorTotal = new ArrayList<Double>();
        ArrayList<Double> valorSubsidioTransporte = new ArrayList<Double>();
        ArrayList<Double> valorPrestacionSalud = new ArrayList<Double>();
        ArrayList<Double> valorPrestacionPension = new ArrayList<Double>();
        ArrayList<Double> valorPrestacionARP = new ArrayList<Double>();
        ArrayList<Double> valorSalarioDevengado = new ArrayList<Double>();

        int diasDelMes = fechaGeneracionNomina.getActualMaximum(Calendar.DAY_OF_MONTH);
 
        int cantidadDias[] = {15, diasDelMes-15};

        double salarioTotalDevengado = 0;
        double totalValorEmpleados = 0;
        double arpTotal = 0;
        double transporteTotal = 0;

        for(Empleado e: empleados){
              
            if( !e.getEstado().equals("Despedido") && !e.getEstado().equals("Jubilado")){
                listaEmpleados.add(e);
                
                if (SIRHApp.getInstance().getAdmCambios().compararFecha(e.getFechaDeModificacion(), fechaGeneracionNomina)
                         != 0){
                    e.setBonos(new ArrayList());
                    e.setFallas(new ArrayList());
                    e.setHorasExtra(new ArrayList());
                }

                Cargo cargoBuscado = buscarCargo(cargos, e.getCargoAsociado().getCambiosCargos().getId());

                double salario = Double.valueOf(cargoBuscado.getSalarioBásico() ) * 
                        ( ( Double.valueOf(e.getPorcentajeSalarioBas()) )/100);
                
                int cantidadDiasTrabajados = cantidadDias[tipoQuincena];
                List<Falla> fallas = e.getFallas();
                for (Falla fa: fallas){
                    cantidadDiasTrabajados -= 1;
                }

                diasTrabajados.add(cantidadDiasTrabajados);

                double valorDias = (salario/diasDelMes) * cantidadDiasTrabajados;
                valorDiasTrabajados.add( valorDias) ;

                Integer[] horasExtras = new Integer[4];
                horasExtras[0] = 0; horasExtras[1] = 0; horasExtras[2] = 0; horasExtras[3] = 0;
 
                for (HoraExtra he: e.getHorasExtra()){
                    horasExtras[he.getTipoHoraExtra().ordinal()] += he.getCantidadHoras();
                }

                tiposDeHorasExtras.add(horasExtras);
                
                Calendar calProceso = new GregorianCalendar( fechaGeneracionNomina.get(Calendar.YEAR),
                                                fechaGeneracionNomina.get(Calendar.MONTH),
                                                fechaGeneracionNomina.get(Calendar.DATE));

                int cantidadHorasQuincenales = 0;
                if (tipoQuincena == 1){
                    calProceso.set(Calendar.DATE, 15);
                    cantidadHorasQuincenales = e.getCargoAsociado().getHorario().getTotalHoras(calProceso, fechaGeneracionNomina);
                }

                else{
                   calProceso.set(Calendar.DATE, 1);
                   
                   Calendar calProcesoQuincena = fechaGeneracionNomina;
                   calProcesoQuincena.set(Calendar.DATE, 16);
                   cantidadHorasQuincenales = e.getCargoAsociado().getHorario().getTotalHoras(calProceso, calProcesoQuincena);
                }

                double valorHoras = (horasExtras[0]*(valorDias/cantidadHorasQuincenales)*( Double.valueOf(prestaciones.get( buscarIndice(prestaciones, prestacionHoraDiurna) ).getPorcentajeEmpleado()) )) +
                                (horasExtras[1]*(valorDias/cantidadHorasQuincenales)*Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionHoraNocturna) ).getPorcentajeEmpleado() )) +
                                (horasExtras[2]*(valorDias/cantidadHorasQuincenales)*Double.valueOf(prestaciones.get( buscarIndice(prestaciones, prestacionHoraFestiva) ).getPorcentajeEmpleado() ) )+
                                (horasExtras[3]*(valorDias/cantidadHorasQuincenales)*Double.valueOf(prestaciones.get( buscarIndice(prestaciones, prestacionHoraFestivaNocturna) ).getPorcentajeEmpleado() )) ;
                
                valorHorasExtras.add( valorHoras );

                double valorBono = 0;
                for(Bono bo: e.getBonos()){
                    valorBono += bo.getCantidadBono();
                }

                valorBonos.add(valorBono);

                double valorTotalEmpleado = valorDias + valorHoras + valorBono;
                valorTotal.add( valorTotalEmpleado );

                totalValorEmpleados += valorTotalEmpleado;

                double costoSubsidioTransporte = 0;
                if ( Double.valueOf(cargoBuscado.getSalarioBásico())*2 < Double.valueOf(prestaciones.get( buscarIndice(prestaciones, prestacionSalarioMinimo) ).getPorcentajeEmpleado() )&&
                        tipoQuincena == 0){
                    costoSubsidioTransporte = Double.valueOf(prestaciones.get( buscarIndice(prestaciones, prestacionSubsidioTransporte) ).getPorcentajeEmpleado());
                }

                transporteTotal += costoSubsidioTransporte;
                valorSubsidioTransporte.add(costoSubsidioTransporte);

                double costoPrestacionSalud = valorTotalEmpleado * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionSalud) ).getPorcentajeEmpleado()) /100);
                valorPrestacionSalud.add( costoPrestacionSalud );

                double costoPrestacionPension = valorTotalEmpleado * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionPension) ).getPorcentajeEmpleado() ) / 100 );
                valorPrestacionPension.add( costoPrestacionPension );

                double costoPrestacionARP = valorTotalEmpleado * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionARP) ).getPorcentajeCompañia() )  / 100 );
                valorPrestacionARP.add( costoPrestacionARP );

                arpTotal += costoPrestacionARP;

                double valorSalarioEmpleado = (valorTotalEmpleado + costoSubsidioTransporte) - (costoPrestacionSalud + costoPrestacionPension);
                valorSalarioDevengado.add( valorSalarioEmpleado );

                salarioTotalDevengado += valorSalarioEmpleado;
            }
        }

        double saludEmpleador = totalValorEmpleados * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones,prestacionSalud) ).getPorcentajeCompañia() ) / 100);
        double pensionEmpleador = totalValorEmpleados * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionPension) ).getPorcentajeCompañia() )/ 100);
        double senaParafiscales = totalValorEmpleados * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionSena) ).getPorcentajeCompañia() ) / 100 );
        double icbfParafiscales = totalValorEmpleados * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionICBF) ).getPorcentajeCompañia() ) / 100 );
        double cajasDeCompensacionParafiscales = totalValorEmpleados * ( Double.valueOf( prestaciones.get( buscarIndice(prestaciones, prestacionCajasCompensacion) ).getPorcentajeCompañia() ) / 100 );

        double totalNomina = saludEmpleador + pensionEmpleador + senaParafiscales
                            + icbfParafiscales + cajasDeCompensacionParafiscales
                            + arpTotal + salarioTotalDevengado;

        GenerarPDF generarPDF = new GenerarPDF();
        generarPDF.crearPDF(fechaGeneracionNomina, "Reportes De Nomina", listaEmpleados, cargos, diasTrabajados, valorDiasTrabajados, tiposDeHorasExtras,
                valorHorasExtras, valorBonos, valorTotal, totalValorEmpleados, valorSubsidioTransporte, valorPrestacionSalud, valorPrestacionPension, valorPrestacionARP,
                valorSalarioDevengado, saludEmpleador, pensionEmpleador, saludEmpleador, senaParafiscales, icbfParafiscales, cajasDeCompensacionParafiscales, totalNomina);
    }

    private int buscarIndice(ArrayList<Prestacion> prestaciones, int ID){
        for (Prestacion p : prestaciones){
            if (p.getIdPrestacion() == ID){
                return prestaciones.indexOf(p);
            }
        }
        return -1;
    }
    
    public Cargo buscarCargo(ArrayList<Cargo> cargos, long ID){
        for (Cargo c : cargos){
            if ((long)c.getCambiosCargos().getId() == ID){
                return c;
            }
        }
        return null;
    }

    private static final int prestacionHoraDiurna = 1;
    private static final int prestacionHoraNocturna = 2;
    private static final int prestacionHoraFestiva = 3;
    private static final int prestacionHoraFestivaNocturna = 4;
    private static final int prestacionSubsidioTransporte = 5;
    private static final int prestacionSalarioMinimo = 6;
    private static final int prestacionSalud = 7;
    private static final int prestacionPension = 8;
    private static final int prestacionARP = 9;
    private static final int prestacionSena = 10;
    private static final int prestacionICBF = 11;
    private static final int prestacionCajasCompensacion = 12;

}
